package hello;

import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
        //添加cas认证
        auth.authenticationProvider(casAuthenticationProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint())  //添加cas认证切面
                .and()
                .addFilter(casAuthenticationFilter())   //添加cas认证filter
                .addFilterBefore(logoutFilter(), LogoutFilter.class)    //添加cas登出filter
                .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class)   //添加cas单点登录filter
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

    @Bean
    public ServiceProperties serviceProperties(){
        ServiceProperties serviceProperties = new ServiceProperties();
        serviceProperties.setSendRenew(false);
        serviceProperties.setService("http://localhost:8090/login");   //当前客户端登录地址
        serviceProperties.setAuthenticateAllArtifacts(true);
        return serviceProperties;
    }

    @Bean
    public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
        CasAuthenticationFilter filter = new CasAuthenticationFilter();
        filter.setAuthenticationManager(authenticationManager());
        filter.setFilterProcessesUrl("/login");
        return filter;
    }

    @Bean
    public CasAuthenticationEntryPoint casAuthenticationEntryPoint(){
        CasAuthenticationEntryPoint point = new CasAuthenticationEntryPoint();
        point.setLoginUrl("http://localhost:8080/login");  //cas服务端登录地址
        point.setServiceProperties(serviceProperties());
        return point;
    }

    @Bean
    public CasAuthenticationProvider casAuthenticationProvider(){
        //cas票据认证地址设置
        Cas30ServiceTicketValidator validator = new Cas30ServiceTicketValidator("http://localhost:8080");
        CasAuthenticationProvider provider = new CasAuthenticationProvider();
        //cas客户端用户授权方法
        provider.setAuthenticationUserDetailsService(new UserServiceImpl());
        provider.setServiceProperties(serviceProperties());
        provider.setTicketValidator(validator);
        provider.setKey("cas_an_id_for_this_auth_provider_only");
        return provider;
    }

    @Bean
    public SingleSignOutFilter singleSignOutFilter(){
        SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
        singleSignOutFilter.setCasServerUrlPrefix("http://localhost:8090");
        singleSignOutFilter.setIgnoreInitConfiguration(true);
        return singleSignOutFilter;
    }

    @Bean
    public LogoutFilter logoutFilter() throws UnsupportedEncodingException {
        String s = URLEncoder.encode("http://localhost:8090/","utf8");
        //添加service，使cas能够重定向
        String logoutUrl = "http://localhost:8080/logout?service="+s;
        LogoutFilter logoutFilter = new LogoutFilter(logoutUrl,new SecurityContextLogoutHandler());
        //拦截退出的url
        logoutFilter.setFilterProcessesUrl("/logout");
        return logoutFilter;
    }
}